//==============================================================================
//
//  File        : mmpf_graphics.c
//  Description : Firmware Graphic Control Function
//  Author      : Ben Lu
//  Revision    : 1.0
//
//==============================================================================

#include "includes_fw.h"
#include "mmpf_graphics.h"
#include "reg_retina.h"
#include "lib_retina.h"
#include "mmp_reg_graphics.h"
#include "mmp_reg_ibc.h"

#include "mmp_reg_scaler.h"
#include "mmp_reg_icon.h"
#include "mmpf_scaler.h"
#include "mmpf_h264enc.h"
//==============================================================================
//
//                              VARIABLES
//
//==============================================================================

static MMPF_OS_SEMID  m_GraphicSemID;
static GraphicRotDMACallBackFunc *GRAScaleCall = NULL;

//==============================================================================
//
//                              FUNCTION PROTOTYPES
//
//==============================================================================



//------------------------------------------------------------------------------
//  Function    : MMPF_Graphics_Init
//  Description :
//  Note        : put in sys_task:main() or XX_Task() (ex: dsc_Task)
//------------------------------------------------------------------------------

void MMPF_Graphics_Init(void)
{
    AITPS_AIC   pAIC = AITC_BASE_AIC;
	AITPS_GRA   pGRA = AITC_BASE_GRA; 

	pGRA->GRA_SCAL_INT_CPU_EN = 0;
	pGRA->GRA_SCAL_INT_CPU_SR = pGRA->GRA_SCAL_INT_CPU_SR ;

    RTNA_AIC_Open(pAIC, AIC_SRC_GRA, gra_isr_a, AIC_INT_TO_IRQ | AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE | 3);
    RTNA_AIC_IRQ_En(pAIC, AIC_SRC_GRA);
    
	m_GraphicSemID = MMPF_OS_CreateSem(1);

    if(m_GraphicSemID >= 0xFE)
    	RTNA_DBG_Str(0, "XXX m_CaptureDoneSem Failed XXX\r\n");
    
    return;
}
#include "mmpf_usbpccam.h"
#include "mmp_reg_gpio.h"

void MMPF_GRA_ISR(void)
{
    AITPS_GRA   pGRA = AITC_BASE_GRA;
    MMP_USHORT  intsrc;
    
    intsrc = pGRA->GRA_SCAL_INT_CPU_SR & pGRA->GRA_SCAL_INT_CPU_EN;
    pGRA->GRA_SCAL_INT_CPU_SR = intsrc;

	if (intsrc & GRA_YUV420_SCAL_DONE) {
	    pGRA->GRA_SCAL_INT_CPU_EN &= ~(GRA_YUV420_SCAL_DONE);
#if 0	    
	    if (MMPF_OS_ReleaseSem(m_GraphicSemID) != OS_NO_ERR) {
		    RTNA_DBG_Str(0, "m_GraphicSemID OSSemPost1: Fail \r\n");
		    return;
	    }
#endif
	    if (GRAScaleCall) (*GRAScaleCall)();
	}

	if (intsrc & GRA_SCAL_DONE) {
		pGRA->GRA_SCAL_INT_CPU_EN &= ~(GRA_SCAL_DONE);
#if 0
	    if (MMPF_OS_ReleaseSem(m_GraphicSemID) != OS_NO_ERR) {
			RTNA_DBG_Str(0, "m_GraphicSemID OSSemPost1: Fail \r\n");
		    return;
	    }
#endif
	    if (GRAScaleCall) (*GRAScaleCall)();
	}
}

MMP_ERR MMPF_Graphics_SetScaleAttribute(MMPF_GRAPHICS_BUFATTRIBUTE *bufAttr,                      
										MMPF_GRAPHICS_RECT		 	*rect, 
										MMP_USHORT 					usUpscale, 
										MMPF_GRAPHICS_SCAL_SRC 		srcsel)
{
	AITPS_GRA   pGRA 	= AITC_BASE_GRA;
	MMP_ULONG	longtmp;

#if 0
    ubRet = MMPF_OS_AcquireSem(m_GraphicSemID, GRAPHICS_SEM_TIMEOUT);
    
    if (ubRet == OS_ERR_PEND_ISR) {
        MMPF_OS_AcceptSem(m_GraphicSemID, &usCount);
        if (usCount == 0) {
            RTNA_DBG_Str(0, "m_GraphicSemID OSSemAccept: Fail0\r\n");
            return MMP_GRA_ERR_BUSY;
        }
    }
    else if (ubRet != OS_NO_ERR) {
        RTNA_DBG_Str(0, "m_GraphicSemID OSSemPend: Fail\r\n");
        return MMP_GRA_ERR_BUSY;
	}
#endif

   	if ( (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420) ||
   	     (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE ) )
   	{
	    longtmp = (bufAttr->ulBaseAddr)
    			+ (bufAttr->usLineOffset * rect->usTop) + rect->usLeft;
    			
        pGRA->GRA_SCAL_ADDR_Y_ST = longtmp;

   	    //support for YUV420 lineoffset
   	    if (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE) {
       		longtmp = (bufAttr->ulBaseUAddr)
        			+ (bufAttr->usLineOffset * (rect->usTop >> 1)) + ((rect->usLeft >> 1) << 1);
	        pGRA->GRA_SCAL_ADDR_U_ST = longtmp;
   	    }
   	    else {
       		longtmp = (bufAttr->ulBaseUAddr)
        			+ ((bufAttr->usLineOffset >> 1) * (rect->usTop >> 1)) + (rect->usLeft >> 1);
	        pGRA->GRA_SCAL_ADDR_U_ST = longtmp;

	       	longtmp = (bufAttr->ulBaseVAddr)
    	    		+ ((bufAttr->usLineOffset >> 1) * (rect->usTop >> 1)) + (rect->usLeft >> 1);
        	pGRA->GRA_SCAL_ADDR_V_ST = longtmp;
    	}

        pGRA->GRA_SCAL_ADDR_Y_OFST = bufAttr->usLineOffset - rect->usWidth;
        
        if (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE) {
   	        pGRA->GRA_SCAL_ADDR_U_OFST = bufAttr->usLineOffset - rect->usWidth;
        }
        else {
            pGRA->GRA_SCAL_ADDR_U_OFST = ((bufAttr->usLineOffset - rect->usWidth) >> 1);
            pGRA->GRA_SCAL_ADDR_V_OFST = pGRA->GRA_SCAL_ADDR_U_OFST;
        }
   	}
    else if (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV422)
    {
	    longtmp = (bufAttr->ulBaseAddr)
    	    	+ ((bufAttr->usLineOffset) * (rect->usTop)) 
	    	    + ((rect->usLeft) * (2));
	    	    
	    // setting for graphic engine
    	pGRA->GRA_SCAL_ADDR_Y_ST = longtmp;
        pGRA->GRA_SCAL_ADDR_U_ST = (bufAttr->usLineOffset);
   	}
    else 
    {
        longtmp = (bufAttr->ulBaseAddr)
		    	+ ((bufAttr->usLineOffset) * (rect->usTop)) 
    			+ ((rect->usLeft) * (MMP_USHORT)(bufAttr->colordepth));
    			
        // setting for graphic engine
    	pGRA->GRA_SCAL_ADDR_Y_ST = longtmp;
        pGRA->GRA_SCAL_ADDR_U_ST = (bufAttr->usLineOffset);
    }

    pGRA->GRA_SCAL_W = (rect->usWidth);
    pGRA->GRA_SCAL_H = (rect->usHeight);

	pGRA->GRA_SCAL_UP_FACT = GRA_SCALUP(usUpscale);

	if (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_16) {
		pGRA->GRA_SCAL_FMT = GRA_SCAL_MEM_RGB565;
	}		
	else if (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_24) {
		pGRA->GRA_SCAL_FMT = GRA_SCAL_MEM_RGB888;
	}		
	else if (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV422) {
		pGRA->GRA_SCAL_FMT = GRA_SCAL_MEM_YUV422;
	}
	else if ( (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420) ||
	          (bufAttr->colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE ) )
	{
		pGRA->GRA_SCAL_FMT = GRA_SCAL_MEM_RGB565;
	}

#if 0
	MMPF_OS_ReleaseSem(m_GraphicSemID);
#endif

    return MMP_ERR_NONE;
}

MMP_ERR MMPF_Graphics_Scale(MMPF_GRAPHICS_BUFATTRIBUTE 	src,
                            MMPF_GRAPHICS_BUFATTRIBUTE 	dst,
                            GraphicRotDMACallBackFunc 	*GRACallBack,
                            MMP_UBYTE  					ubPixelDelay,
                            MMP_USHORT 					usWaitMs,
                            MMP_UBYTE  					ubIBCPipeNum)
{
    AITPS_GRA   pGRA = AITC_BASE_GRA;
    AITPS_IBC   pIBC = AITC_BASE_IBC;
    volatile AITPS_IBCP  pIbcPipeCtl;

#if 0
    ubRet = MMPF_OS_AcquireSem(m_GraphicSemID, usWaitMs);
    
    if(ubRet == 1) 
    { 	// timeout error
        RTNA_DBG_Str(0, "m_GraphicSemID OSSemPend: Fail\r\n");
        return MMP_GRA_ERR_BUSY;
    } 
    else if (ubRet == 2) 
    { 	// aquire in ISR
        MMPF_OS_AcceptSem(m_GraphicSemID, &usCount);
        if(usCount == 0){
            RTNA_DBG_Str(0, "m_GraphicSemID OSSemAccept: Fail\r\n");
            return MMP_GRA_ERR_BUSY;
        }
    }
#endif
        
	#if (CHIP == VSN_V2)
	pGRA->GRA_SCAL_FLOW_CTL = GRA_SCAL_BUSY_CTL;
	#endif
	
	/* Actual pixel delay = (1+ubPixelDelay) */
	pGRA->GRA_SCAL_PIXL_DLY = ubPixelDelay;

	switch(ubIBCPipeNum)
	{
		case MMPF_IBC_PIPE_0:
			pIbcPipeCtl = &(pIBC->IBCP_0);
		break;	
		case MMPF_IBC_PIPE_1:
			pIbcPipeCtl = &(pIBC->IBCP_1);
		break;	
		case MMPF_IBC_PIPE_2:
			pIbcPipeCtl = &(pIBC->IBCP_2);
		break;		
		default:
			pIbcPipeCtl = &(pIBC->IBCP_0);
		break;
	}
    
    if ((src.colordepth == MMPF_GRAPHICS_COLORDEPTH_16) ||
        (src.colordepth == MMPF_GRAPHICS_COLORDEPTH_24) ||
        (src.colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV422))
	{
    	if (pGRA->GRA_SCAL_EN & GRA_SCAL_ST) {
    	    DBG_S(3, "GRAPHIC SCAL BUSY\r\n");
    		return MMP_ERR_NONE;
        }
        pGRA->GRA_SCAL_INT_CPU_SR = GRA_SCAL_DONE;
        pGRA->GRA_SCAL_INT_CPU_EN = GRA_SCAL_DONE;
        pGRA->GRA_SCAL_ADDR_Y_ST  = src.ulBaseAddr;
        GRAScaleCall 			  = GRACallBack;
        pGRA->GRA_SCAL_EN 		  = GRA_SCAL_ST;
    }
    else if ( (src.colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420) ||
              (src.colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE ) )
    {
        if (pGRA->GRA_SCAL_EN & GRA_YUV420_SCAL_ST) {
    	    DBG_S(3, "GRAPHIC SCAL420 BUSY\r\n");
    	    return MMP_ERR_NONE;
        }
        pGRA->GRA_SCAL_ADDR_Y_ST = src.ulBaseAddr;
        pGRA->GRA_SCAL_ADDR_U_ST = src.ulBaseUAddr;
        pGRA->GRA_SCAL_ADDR_V_ST = src.ulBaseVAddr;
        
        if (dst.ulBaseAddr) {
            pIbcPipeCtl->IBC_ADDR_Y_ST = dst.ulBaseAddr;
            pIbcPipeCtl->IBC_ADDR_U_ST = dst.ulBaseUAddr;
            pIbcPipeCtl->IBC_ADDR_V_ST = dst.ulBaseVAddr;
        }
        
        GRAScaleCall 			  = GRACallBack;
        pGRA->GRA_SCAL_INT_CPU_SR = GRA_YUV420_SCAL_DONE;
        pGRA->GRA_SCAL_INT_CPU_EN = GRA_YUV420_SCAL_DONE;

        if (src.colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420)
            pGRA->GRA_SCAL_EN = GRA_YUV420_SCAL_ST;
        else if (src.colordepth == MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE)
            pGRA->GRA_SCAL_EN = GRA_YUV420_SCAL_ST | GRA_YUV420_INTERLEAVE;
    }
    else 
    {
        RTNA_DBG_Str(0, "Unsupported color format\r\n");
    }
    return MMP_ERR_NONE;
}
